home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
disk
/
cluster2.zip
/
SOURCE.ZIP
/
BOXMGR.BU
next >
Wrap
Text File
|
1996-07-06
|
26KB
|
584 lines
$COMPILE UNIT ".\BOXMGR.PBU"
$CODE SEG "SCRNLIB"
$CPU 8086 ' Make compatible with XT systems
$LIB ALL OFF ' Turn off all PowerBASIC libraries
$ERROR ALL OFF ' Turn off all PowerBASIC error checking
$OPTIMIZE SIZE ' Optimize for smaller code
DEFINT A-Z ' Required for all numeric functions, forces PB to not
' include floating point in UNIT (makes it smaller)
'╒═══════════════════════════════════════════════════════════════════════════╕
'│ This library will manage boxes, saving and restoring the │
'│ underlying screen areas as needed. It also has some other │
'│ handy routines, such as a scrolling text viewer, a routine │
'│ to set PowerBASIC's PRINT output to only be in the current box │
'│ │
'│ This code is free for use, but is copyright Nathan C. Durland III │
'│ All rights reserved │
'╞═══════════════════════════════════════════════════════════════════════════╡
'│ Started Jun 10, 1996 -- Bud Durland │
'╞═══════════════════════════════════════════════════════════════════════════╡
'│ Routines are documented with liberal comments in the routine itself │ │
'│ │
'│ However, a quick overview: │
'│ │
'│ This routine will simplify creating and using screen text boxes. │
'│ Each of the routines is pretty well commented and should be │
'│ self-explainatory. Let me touch a couple of the highlights: │
'│ │
'│ 1) always remember to call BoxInit before using any of hte other │
'│ functions listed here. This routine sets up storage arrays │
'│ and etc. │
'│ │
'│ 2) To specify colors, you will be passing the routines attribute │
'│ values, which are a computed using the numeric value of the │
'│ foreground and background colors you want. the │
'│ MakeAttr%(Fore%,Back%) function will compute attributes for │
'│ you. Likewise, the PB3BOXES.INC file has pre-defined │
'│ constants for most of the colors. So, you can do something │
'│ like Box1Attr% = MakeAttr%(%BrightWhite,%Blue) │
'│ │
'│ 3) If you use -1 instead of an attribute value in PrtBox, PrtEOL, │
'│ ClearBox, or BoxTiltle, the default color attribute specified │
'│ when the box was created will be used. │
'│ │
'╘═══════════════════════════════════════════════════════════════════════════╛
DECLARE SUB GetStrLoc() ' internal string locator in RTL
$INCLUDE ".\PB3BOXES.HDR" ' includes defs & declares for all modules.
SUB BoxInit(BYVAL MB%) LOCAL PUBLIC
'╒═══════════════════════════════════════════════════════════════════════╕
'│This sub initializes the arrays used to store window data │
'│ │
'│ MB% is the the maximum numberof boxes you will be using. 5 is the │
'│ default │
'│ │
'╘═══════════════════════════════════════════════════════════════════════╛
CurrentBox% = 0
MaxBoxes% = MB%
IF MaxBoxes% < 1 THEN MaxBoxes% = 5
DIM BoxParms%(1:MaxBoxes%,1:6) ' stores Size, Color, & border type
DIM SaveText$(1:MaxBoxes%) ' stores saved text
DIM BorderText$(0:3) ' Different box borders
BorderText$(0) = CHR$( 32, 32, 32, 32, 32, 32) ' no border
BorderText$(1) = CHR$(196,179,218,191,192,217) ' single
BorderText$(2) = CHR$(205,186,201,187,200,188) ' double
BorderText$(3) = CHR$(219,219,219,219,219,219) ' Solid
END SUB
SUB MakeBox(BYVAL Row%, BYVAL Col%, BYVAL Rows%, BYVAL Cols%, _
BYVAL BoxAttr%, BYVAL Border%) LOCAL PUBLIC
'╒══════════════════════════════════════════════════════════════════════════╕
'│ MAKEBOX -- put a box on the screen. underlying text is preserved │
'│ so it can be put back by the RemoveBox routine │
'│ │
'│Row% = Top row of box │
'│Col% = Left column │
'│Rows% = length of box │
'│Cols% = Width of box │
'│BoxAttr% = color attribute for box │
'│Border% = border style to use 0-None 1-single 2-double 3-Solid │
'│ Add 10 to value for "3-d" border │
'╘══════════════════════════════════════════════════════════════════════════╛
IF CurrentBox% = MaxBoxes% THEN EXIT SUB ' no more room for making boxes.
IF Border% < 0 THEN Border% = 1
INCR CurrentBox%,1 ' bump box number
BoxParms%(CurrentBox%,1) = Row% ' Save infor about Box
BoxParms%(CurrentBox%,2) = Col%
BoxParms%(CurrentBox%,3) = Rows%
BoxParms%(CurrentBox%,4) = Cols%
BoxParms%(CurrentBox%,5) = BoxAttr%
BoxParms%(CurrentBox%,6) = Border% MOD 10
lAttr% = BoxAttr%
' Get component colors of box attribute for use in 3d effects
IF Border% > 9 THEN
CALL ReturnAttr(BoxAttr%, TheFore%, TheBack%)
IF TheFore% = TheBack% THEN ' caller wants same fore & back colors
LowFore% = TheFore% ' Why? Dunno, but we'll let it happen
HiFore% = TheFore%
ELSE
LowFore% = TheFore% MOD 8 ' low intesity colors are < 8
HiFore% = LowFore% + 8 ' high intensity is => 8
END IF
lAttr% = MakeAttr%(LowFore%,TheBack%)
hAttr% = MakeAttr%(HiFore%,TheBack%)
END IF
' Save the underlying text, then create the box!
temp$ = ""
CALL QSAVE(Row%, Col%, Rows%, Cols%, temp$)
SaveText$(CurrentBox%) = temp$
CALL QBOX(Row%, Col%, Rows%, Cols%, lAttr%, (Border% MOD 10))
IF Border% > 10 THEN
CALL QATTR((Row% + Rows%)-1,Col%,1,Cols%,hAttr%)
CALL QATTR(Row%+1,(Col%+Cols%)-1,Rows%-1,1,hAttr%)
END IF
END SUB
SUB RemoveBox LOCAL PUBLIC
'╒═════════════════════════════════════════════════════════════════════╕
'│ RemoveBox -- Takes a box off the screen, and replaces it with the │
'│ saved underlying data │
'╘═════════════════════════════════════════════════════════════════════╛
IF CurrentBox% < 1 THEN EXIT SUB
Row% = BoxParms%(CurrentBox%,1)
Col% = BoxParms%(CurrentBox%,2)
Rows% = BoxParms%(CurrentBox%,3)
Cols% = BoxParms%(CurrentBox%,4)
temp$ = SaveText$(CurrentBox%)
CALL QREST(Row%, Col%, Rows%, Cols%, temp$)
DECR CurrentBox%
END SUB
SUB ClearBox(BYVAL Char%, BYVAL Attr%) LOCAL PUBLIC
'╒════════════════════════════════════════════════════════════════════════════╕
'│ Clears the current box using the specified character and attribute │
'╞════════════════════════════════════════════════════════════════════════════╡
'│Char% -- ASCII value of character to use. If < 0, a space is used. │
'│Attr% -- Color attribute to use. if < 0, the default for the box is used │
'╘════════════════════════════════════════════════════════════════════════════╛
IF CurrentBox% = 0 THEN EXIT SUB
IF Char% < 0 THEN Char% = 32
IF Attr% < 0 THEN Attr% = BoxParms%(CurrentBox%,5)
Row% = BoxParms%(CurrentBox%,1)
Col% = BoxParms%(CurrentBox%,2)
Rows% = BoxParms%(CurrentBox%,3)
Cols% = BoxParms%(CurrentBox%,4)
IF BoxParms%(CurrentBox%,6) > 0 THEN ' account for border!
INCR Row%,1
INCR Col%,1
DECR Rows%,2
DECR Cols%,2
END IF
IF (Rows% < 1) OR (Cols% < 1) THEN EXIT SUB
CALL QFILL(Row%,Col%,Rows%,Cols%,Char%,Attr%)
END SUB
SUB PrtBox(BYVAL Row%, BYVAL Col%, BYVAL TheText$, BYVAL Attr%) LOCAL PUBLIC
'╒═══════════════════════════════════════════════════════════════════════╕
'│PrtBox -- prints the specified text in the current box │
'│ at the specified row & column. │
'╞═══════════════════════════════════════════════════════════════════════╡
'│Row, Col = where to print; relative to upper left corner │
'│ of the current box. Row is required. If Col = 0, │
'│ the text is centered on row │
'│ │
'│TheText$ = what to print. │
'│ │
'│Attr = the attribute to use. If this is =-1, then the │
'│ default color for the current box is used. │
'╘═══════════════════════════════════════════════════════════════════════╛
IF CurrentBox% = 0 THEN EXIT SUB ' no boxes on screen
IF Attr% = -1 THEN Attr% = BoxParms%(CurrentBox%,5) ' use box color
RealRow% = Row% + BoxParms%(CurrentBox%,1) 'compute row to use
IF BoxParms%(CurrentBox%, 6) = 0 THEN DECR RealRow%,1 'allow for no border
IF Col% = 0 THEN ' We're centering the print
LeftCol% = BoxParms%(CurrentBox%,2) ' get left column
RightCol% = (LeftCol% + BoxParms%(CurrentBox%,4)) ' add the width
IF BoxParms%(CurrentBox%,6) > 0 THEN ' Adjust for border
INCR LeftCol%,1
DECR RightCol%,1
END IF
CALL QPRINTC(RealRow%, LeftCol%, RightCol%, TheText$, Attr%)
ELSE
RealCol% = ABS(Col%) + BoxParms%(CurrentBox%,2)
IF BoxParms%(CurrentBox%, 6) = 0 THEN DECR RealCol%,1
CALL QPRINT(RealRow%, RealCol%, TheText$, Attr%)
END IF
END SUB
SUB PrtEOL(BYVAL Row%, BYVAL Col%, BYVAL TheText$, BYVAL Attr%) LOCAL PUBLIC
'╒════════════════════════════════════════════════════════════════════════╕
'│This is the same as PrtBox, except that the specified row is erased │
'│before the text is printed. │
'╘════════════════════════════════════════════════════════════════════════╛
IF CurrentBox% = 0 THEN EXIT SUB ' no boxes on screen
Attr1% = BoxParms%(CurrentBox%,5) ' use box color
IF Col% < 0 THEN Col% = 1
RealRow% = Row% + BoxParms%(CurrentBox%,1) 'compute row to use
RealCol% = Col% + BoxParms%(CurrentBox%,2) 'compute column
dLen% = BoxParms%(CurrentBox%,4) - (Col% + 1) ' how many columns
IF BoxParms%(CurrentBox%, 6) = 0 THEN ' allow for no border
DECR RealRow%,1
DECR RealCol%,1
ELSE
DECR dLen%,2
END IF
a$ = SPACE$(dLen%) ' make a string of blanks
CALL QPRINT(RealRow%, RealCol%, a$, Attr1%) ' print it
CALL PrtBox(Row%, Col%, TheText$, Attr%) ' put the text in the box
END SUB
SUB NukeBoxes(BYVAL StopMe%) LOCAL PUBLIC
'╒══════════════════════════════════════════════════════════════════════╕
'│ NukeBoxes -- Use this to remove multiple boxes at once. │
'╞══════════════════════════════════════════════════════════════════════╡
'│StopMe% -- Number of boxes to be remain on the screen │
'│ │
'│i.e. CALL NukeBoxes(1) removes all boxes except the first one │
'╘══════════════════════════════════════════════════════════════════════╛
WHILE CurrentBox% > StopMe%
CALL RemoveBox
WEND
END SUB
SUB SetBoxColor(BYVAL TheBox%, BYVAL NewAttr%) LOCAL PUBLIC
'╓─────────────────────────────────────────────────────────────────────────────╖
'║ Sets a new default color for the specified box. ║
'║ This routine does not recolor the box to the new attribute; call ║
'║ ClearBox(-1,-1) ║
'║ ║
'║TheBox% -- Number of box to be changed. If = -1, the current box is used. ║
'║NewAttr% -- New color to assign the box. ║
'╙─────────────────────────────────────────────────────────────────────────────╜
IF TheBox% > MaxBoxes% THEN EXIT SUB
IF TheBox% < 1 THEN TheBox% = CurrentBox%
Boxparms%(TheBox%, 5) = NewAttr%
END SUB
SUB BoxTitle(BYVAL Where%, BYVAL Text$, BYVAL Attr%) LOCAL PUBLIC
'╒═══════════════════════════════════════════════════════════════════════════╕
'│ Puts a box in one of 6 locations. │
'│ │
'│ ┌─1────2─────3─┐ │
'│ │ │ │
'│ │ │ │
'│ │ │ │
'│ └─4────5─────6─┘ │
'│ │
'│ Where% = WHich location to use │
'│ Text$ = The text of the title. │
'│ Attr% = Attribute to use. -1 = use the current box color │
'│ │
'│ ***** If the box's border type is 0, title are not allowed!! ****** │
'╘═══════════════════════════════════════════════════════════════════════════╛
' titles not allowed if box border type is 0 (no border)
IF BoxParms%(CurrentBox%,6) = 0 THEN EXIT SUB
Row% = BoxParms%(CurrentBox%,1) 'find out where box is
Col% = BoxParms%(CurrentBox%,2) ' on the screen
Rows% = BoxParms%(CurrentBox%,3)
Cols% = BoxParms%(CurrentBox%,4)
IF Attr% < 0 THEN Attr% = BoxParms%(CurrentBox%,5) ' get the color to use
Border% = BoxParms%(CurrentBox%,6) ' find border type
SELECT CASE Border% ' set "brackets" around
CASE 0: Text$ = " " + Text$ + " " ' the title text
CASE 1: Text$ = "┤" + Text$ + "├"
CASE 2: Text$ = "╣" + Text$ + "╠"
CASE 3: Text$ = "▌" + Text$ + "▐"
CASE 4: Text$ = " " + Text$ + " "
END SELECT
tLen% = LEN(Text$)
IF Where% > 3 THEN INCR Row%,(Rows%-1) ' determine where to
SELECT CASE Where% ' print the title text
CASE 1,4 ' left side of window
INCR Col%,1
CASE 2,5 ' center of window
Col% = (Col% + (Cols% \ 2)) - (tLen% \ 2)
CASE 3,6 ' right side of window
Col% = (Col% + Cols% - 1) - tlen%
END SELECT
CALL QPRINT(Row%, Col%, Text$, Attr%) ' print it!
END SUB
SUB ScrollBox(BYVAL Direction%, BYVAL HowMany%) LOCAL PUBLIC
'╓──────────────────────────────────────────────────────────────────────╖
'║ Scrolls the text in the box up or down some number of rows ║
'║ ║
'║ Direction% -- if < 1, scroll down. if =>1, scroll up ║
'║ HowMany% -- how many rows to scroll ║
'╙──────────────────────────────────────────────────────────────────────╜
IF CurrentBox% = 0 THEN EXIT SUB
IF HowMany% = 0 THEN EXIT SUB
Row% = BoxParms%(CurrentBox%,1)
Col% = BoxParms%(CurrentBox%,2)
Rows% = BoxParms%(CurrentBox%,3)
Cols% = BoxParms%(CurrentBox%,4)
Attr% = Boxparms%(CurrentBox%,5)
IF BoxParms%(CurrentBox%,6) > 0 THEN ' account for border!
INCR Row%,1
INCR Col%,1
DECR Rows%,2
DECR Cols%,2
END IF
IF Direction% > 0 THEN
CALL ScrollUp(Row%, Col%, Rows%, Cols%, Attr%, HowMany%)
ELSE
CALL ScrollDown(Row%, Col%, Rows%, Cols%, Attr%, HowMany%)
END IF
END SUB
SUB SetViewText(BYVAL XOff%, BYVAL YOff%) LOCAL PUBLIC
'╓───────────────────────────────────────────────────────────────────────╖
'║ This sub will set the VIEW TEXT command so that the output from any ║
'║ PRINT commands will be placed in the current box. ║
'║ ║
'║ Xoff% -- Column offset added to the text window ║
'║ Yoff% -- Row offset added to the text window ║
'║ ║
'║ NOTE: Removing or creating a box does not change VIEW TEXT. ║
'║ You must call this routing to PRINT text to the current ║
'║ box ║
'╙───────────────────────────────────────────────────────────────────────╜
IF CurrentBox% < 1 THEN
VIEW TEXT (1,1) - (80,24)
EXIT SUB
END IF
TheRow% = BoxParms%(CurrentBox%,1)
TheCol% = BoxParms%(CurrentBox%,2)
RowCnt% = BoxParms%(CurrentBox%,3)
ColCnt% = BoxParms%(CurrentBox%,4)
Attr% = BoxParms%(CurrentBox%,5)
Border% = BoxParms%(CurrentBox%,6)
Col1% = TheCol% + ColCnt% - 1
Row1% = TheRow% + RowCnt% - 1
IF Border% > 0 THEN
INCR TheRow%,1
DECR Row1%,1
INCR TheCol%,1
DECR Col1%,1
END IF
TheRow% = TheRow% + YOff%
TheCol% = TheCol% + XOff%
VIEW TEXT (TheCol%,TheRow%) - (Col1%,Row1%)
CALL ReturnAttr(Attr%, f%, b%)
COLOR f%, b%
END SUB
FUNCTION MsgBox$(BYVAL TheMsg$, BYVAL GoodKeys$, BYVAL Attr%) LOCAL PUBLIC
'╒══════════════════════════════════════════════════════════════════════════╕
'│ this function will display the given message on the screen, and will │
'│ wait for the user to press a key. When called, TheMsg$ should contain │
'│ the lines of text to be displayed (up to {screen size - 2}). Each │
'│ line should be separated by a line feed -- CHR$(10) │
'╞══════════════════════════════════════════════════════════════════════════╡
'│ The variable GoodKeys$ is sent in with the keystrokes that are valid │
'│ All of those keys will be accepted. If GoodKeys$ is null (""), then │
'│ any key will be accepted and returned │
'╘══════════════════════════════════════════════════════════════════════════╛
TheMsg$ = RTRIM$(TheMsg$, ANY CHR$(10,13,32))
TheMsg$ = REMOVE$(TheMsg$, ANY CHR$(13))
GoodKeys$ = UCASE$(GoodKeys$)
LinesNeeded% = TALLY(TheMsg$,CHR$(10)) + 1
REDIM MBox$(1:LinesNeeded%)
MaxWidth% = 0
FOR x% = 1 TO LinesNeeded% ' extract lines to an array
a$ = EXTRACT$(TheMsg$,CHR$(10)) ' get next one
IF LEN(a$) > MaxWidth% THEN MaxWidth% = LEN(a$) ' check width
MBox$(x%) = a$ ' remember it
IF x% <> LinesNeeded% THEN ' point past CHR$(10)
TheMsg$ = MID$(TheMsg$,LEN(a$)+2)
END IF
NEXT x%
BoxLines% = LinesNeeded% + 2 ' setup to draw box
BoxWidth% = MaxWidth% + 2
IF BoxLines% > PbvScrnRows THEN BoxLines% = pbvScrnRows
IF BoxWidth% > PbvScrnCols THEN BoxWidth% = pbvScrnCols
TopLine% = (pbvScrnRows - BoxLines%) / 3 ' Center the box
LeftCol% = (pbvScrnCols - BoxWidth%) / 2
IF TopLine% < 1 THEN TopLine% = 1
CALL MakeBox(TopLine%, LeftCol%, BoxLines%, BoxWidth%, Attr%, 1)
FOR x% = 1 TO LinesNeeded%
CALL PrtBox(x%,0,MBox$(x%),-1)
NEXT x%
TheVal$ = ""
WHILE LEN(TheVal$) = 0
WHILE NOT INSTAT:WEND
TheVal$ = INKEY$
IF LEN(TheVal$) = 1 THEN TheVal$ = UCASE$(TheVal$)
IF LEN(GoodKeys$) > 0 THEN
IF INSTR(GoodKeys$, TheVal$) = 0 THEN TheVal$ = ""
END IF
WEND
MsgBox$ = TheVal$
CALL RemoveBox
END FUNCTION
FUNCTION MakeAttr%(Fore%, Back%) LOCAL PUBLIC
'╒══════════════════════════════════════════════════════════════════════╕
'│ Creates the value of an attribute byte using Fore% as the foreground │
'│ color and Back% as the background color │
'╘══════════════════════════════════════════════════════════════════════╛
Backgr% = Back% MOD 16 ' No values higher than 16 allowed
Foregr% = Fore% MOD 16
temp% = (Backgr% * 16) + Foregr%
IF Fore% > 15 THEN INCR temp%, 128 ' User wanted das blinken lights
MakeAttr% = temp%
END FUNCTION
SUB ReturnAttr(BYVAL A%, Fore%, Back%) LOCAL PUBLIC
'╒══════════════════════════════════════════════════════════════════════╕
'│ basically the reverse of MakeAttr% -- this will break an attribute │
'│ value into it's component parts: │
'│ │
'│ a% -- attribute value │
'│ Fore% -- Foreground color of attribute │
'│ Back% -- background color of attribute │
'│ │
'╘══════════════════════════════════════════════════════════════════════╛
IF A% < 128 THEN
Fore% = A% MOD 16
Back% = A% \ 16
ELSE
Fore% = ((A% - 128) MOD 16)
Fore% = Fore% + 16
Back% = (A% - 128)\16
END IF
END SUB
SUB ScrollList(BYVAL ItemCount%, ItemList$(), BYVAL CenterIt%) PUBLIC LOCAL
'╒════════════════════════════════════════════════════════════════════╕
'│ Creates a scrolling list of lines. Useful for help screens │
'│ You have to create a box first! │
'│ │
'│ ItemCount% = How many items there are in the list │
'│ ItemList$() = the items to be displayed. │
'│ Centerit% = If non-zero, the items will be centered in the box │
'╘════════════════════════════════════════════════════════════════════╛
IF CenterIt% THEN CCol% = 0 ELSE CCol% = 1
IF BoxParms%(CurrentBox%,6) > 0 THEN
WindowLines% = BoxParms%(CurrentBox%,3) - 3
WindowCenter% = (BoxParms%(CurrentBox%,4) - 2) \ 2
ELSE
WindowLines% = BoxParms%(CurrentBox%,3) - 1
WindowCenter% = (BoxParms%(CurrentBox%,4)) \ 2
END IF
TopPointer% = 1
DispTerm% = %False
WHILE NOT DispTerm%
Lptr% = 1
CALL ClearBox(-1,-1)
IF TopPointer% < 1 THEN TopPointer% = 1
FOR x% = TopPointer% to (TopPointer% + WindowLines%)
IF x% <= ItemCount% THEN
TheLine$ = ItemList$(x%)
CALL PrtBox(LPtr%,CCol%,TheLine$,-1)
INCR Lptr%,1
END IF
NEXT x%
' Now wait for the user to tell us to do something
AKey$ = Null$
WHILE LEN(AKey$) = 0
IF (TopPointer% > 1) AND (TopPointer% < (ItemCount% - WindowLines%)) THEN
fs$ = CHR$(0,18) ' dbl head arrow
ELSEIF TopPointer% > 1 THEN
fs$ = CHR$(0,24) ' up arrow
ELSEIF TopPointer% < (ItemCount% - WindowLines%) THEN
fs$ = CHR$(0,25) ' down arrow
END IF
CALL BoxTitle(6,fs$,-1)
WHILE NOT INSTAT:WEND
AKey$ = INKEY$
IF LEN(AKey$) = 1 THEN AKey$ = UCASE$(AKey$)
SELECT CASE AKey$
CASE CHR$(27)
CALL ClearBox(-1,-1)
CALL BoxTitle(6,CHR$(0),-1)
EXIT SUB
CASE CHR$(0,73) ' PgUp
IF TopPointer% > 1 THEN
DECR TopPointer%,WindowLines%
ELSE
AKey$ = Null$
END IF
CASE CHR$(0,81) ' PgDn
IF TopPointer% < (ItemCount% - WindowLines%) THEN
INCR TopPointer%,WindowLines%
ELSE
AKey$ = Null$
END IF
CASE CHR$(0,71) ' HOME key
TopPointer% = 1
CASE CHR$(0,79) 'END key
TopPointer% = ItemCount% - WindowLines%
CASE CHR$(0,72) ' Up Arrow
IF TopPointer% > 1 THEN
CALL ScrollBox(0,1)
DECR TopPointer%,1
TheLine$ = ItemList$(TopPointer%)
TheLine$ = REMOVE$(TheLine$, ANY CHR$(1,2))
CALL PrtBox(1,CCol%,TheLine$,-1)
END IF
AKey$ = Null$
CASE CHR$(0,80) 'Down arrow
IF TopPointer% < (ItemCount% - WindowLines%) THEN
CALL ScrollBox(1,1)
INCR TopPointer%,1
TheLine$ = ItemList$(TopPointer% + WindowLines%)
TheLine$ = REMOVE$(TheLine$, ANY CHR$(1,2))
CALL PrtBox(WindowLines% + 1,CCol%,TheLine$,-1)
END IF
AKey$ = Null$
CASE ELSE
AKey$ = Null$
END SELECT
WEND 'AKey$
WEND 'NOT DispTerm
END SUB